/*
 *  cpu_functions.c
 *  
 *              CPU Monitor 
 *
 *    Spring Semester.  044800.    Technion.
 *   Copyright (C) 2006  Evgeny Shulman  and Elizabeth Shtrom 
 */

#include <stdio.h>
#include <stdlib.h>

#include <unistd.h>
#include <fcntl.h>
#include <sched.h>
#include <linux/types.h>
#include <sys/ioctl.h>


#include "cpu_parse_display/cpu_display.h"

#include "cpu_consts.h"
#include "cpu_common.h"
#include "cpu_monitor.h"
#include "cpu_functions.h"



int read_pid (int fd , int *pid ){
	
	int ret = 0;
	ret = ioctl (fd, CPU_MONITOR_IOC_PID, pid);
	if ( ret )
		fprintf(stderr,  "read_regs : ioctl error %d ", ret ) ;
	return ret;
}
int read_regs (int fd , regs_s * regs ){
	
	int ret = 0;
	ret = ioctl (fd, CPU_MONITOR_IOC_GET_REGS, regs);
	if ( ret )
		fprintf(stderr,  "read_regs : ioctl error %d ", ret ) ;
	return ret;
}

int read_gdt (int fd, cm_desc_t * gdt_table) {

	int ret = 0 ;
	ret = ioctl (fd, CPU_MONITOR_IOC_GET_GDT, gdt_table);
	if ( ret )  
		fprintf(stderr,  "read_gdt : ioctl error %d ", ret ) ;
	return ret;
}


int read_ldt (int fd, cm_desc_t * ldt_table) {
	int ret = 0 ;
	ret = ioctl (fd, CPU_MONITOR_IOC_GET_LDT, ldt_table);
	if ( ret  ) 
		fprintf(stderr, "read_ldt : ioctl error %d \n" , ret ) ; 	
		
	return ret;
}

int read_idt (int fd, cm_gate_desc_t * idt_table ) {
	int ret = 0;
	ret = ioctl (fd, CPU_MONITOR_IOC_GET_IDT, idt_table);
	if ( ret )  fprintf(stderr,  "read_idt : ioctl error %d ", ret ) ;
	return ret;
}

int read_pgd ( int fd , unsigned long * pgd_table ){
	int i, ret = 0;
	unsigned long * pgd_table_p = pgd_table;
	pgd_s pgd_arg;
	
	for ( i=0;i<PGD_TABLE_ENTRIES;i+=USER_ENTRIES,pgd_table_p+=USER_ENTRIES){
		pgd_arg.pgd_table=pgd_table_p;	
		pgd_arg.index=i;
		ret = ioctl (fd, CPU_MONITOR_IOC_GET_PGD , &pgd_arg );
		if ( ret ){
			fprintf(stderr,  "read_pgd : ioctl error %d \n", ret ) ;
			break;
		}
	}
	return ret;
}

int read_ptable ( int fd , unsigned long pde , unsigned long * ptable ){
	int i, ret = 0;
	unsigned long * ptable_p = ptable;
	pt_s pt_arg;
	pt_arg.pde=pde;
	
	if (!( pde & DISP_PAGE_PRESENT )){
		fprintf(stderr, "read_ptable : entry not present\n" );
		return -ENTRY_NOT_PRESENT;
	}
		
	if (pde & DISP_PAGE_PSE){
		fprintf(stderr,"read_ptable : the entry doesn't point to a ptable\n" );
		return -PDE_POINTS_TO_PAGE;
	}

	for ( i=0;i<PT_TABLE_ENTRIES;i+=USER_ENTRIES,ptable_p+=USER_ENTRIES){
		pt_arg.pt_table=ptable_p;	
		pt_arg.index=i;
		ret = ioctl (fd, CPU_MONITOR_IOC_GET_PT , &pt_arg );
		if ( ret ){
			fprintf(stderr,  "read_ptable : ioctl error %d \n", ret ) ;
			break;
		}
	}
	return ret;
}

int read_tss (int fd , cm_tss_struct * tss_table ){
	int ret =0 ;
	ret = ioctl (fd, CPU_MONITOR_IOC_GET_TSS, tss_table);
	if ( ret ) fprintf(stderr,  "read_tss : ioctl error %d ", ret ) ;		
	return ret;
}

int read_cpuid (int fd, int op,
	unsigned long *eax,
	unsigned long *ebx,
	unsigned long *ecx,
	unsigned long *edx)
{
	cpuid_s c;
	int ret;
	
	c.op = op	;
	ret = ioctl (fd, CPU_MONITOR_IOC_GET_CPUID, &c);
	if ( ret ) 
	{
		fprintf(stderr,  "read_cpuid : ioctl error %d ", ret ) ;
		return ret;
	}
	
	if( eax) 
		*eax = c.eax; 
	if( ebx) 
		*ebx = c.ebx;
	if( ecx) 
		*ecx = c.ecx;
	if( edx) 
		*edx = c.edx;	
	return 0;
}



int im_start(int fd ){
	int ret;
	ret = ioctl (fd, CPU_MONITOR_IOC_IM_START);
	if ( ret ) 
	{
		fprintf(stderr,  "im_start : ioctl error %d ", ret ) ;
		return  ret;
	}


	PDEBUG("im monitor: started!\n");
	return 0;
}

int im_read (int fd, im_irq_stat_s *im_irq_stat_data){
	int ret;
	ret = ioctl (fd, CPU_MONITOR_IOC_IM_READ, im_irq_stat_data );
	if ( ret ) 
	{
		fprintf(stderr,  "im_read : ioctl error %d ", ret ) ;
		return ret ;
	}

		
	PDEBUG("im_read:done!\n");
	return 0;
}
	
int im_stop (int fd){
	int ret;
	ret = ioctl (fd, CPU_MONITOR_IOC_IM_STOP);
	if ( ret ) 
	{
		fprintf(stderr, "im_stop : ioctl error %d ", ret ) ;
		return ret ;
	}


	PDEBUG("im monitor: stopped!\n");
	return 0;
}


int im_reset (int fd){
	int ret;
	ret = ioctl (fd, CPU_MONITOR_IOC_IM_RESET);
	if ( ret ) 
	{
		fprintf(stderr, "im_reset : ioctl error %d ", ret ) ;
		return ret ;
	}

	PDEBUG("im monitor: reset!\n");
	return 0;
}

int im_is_started (int fd){
	int ret;
	int is = 0 ;
	ret = ioctl (fd, CPU_MONITOR_IOC_IM_IS, &is);
	if ( ret ) 
	{
		fprintf(stderr, "im_is_started : ioctl error %d ", ret ) ;
		return ret ;
	}
	PDEBUG("im monitor: started ->%d!\n", is);
	return is;
}


int cpu_set_affinity(int cpu){
	cpu_set_t mask;
	if ( cpu >=0 ) {
		CPU_ZERO(&mask);
		CPU_SET( cpu, &mask);
		PDEBUG("cpu_set_affinity:cpu %d \n", cpu);
	}else{
		return -1;
	}
	
	if ( sched_setaffinity(0, sizeof(mask), &mask) < 0) {
   		fprintf(stderr,"cpu_set_affiniti:sched_setaffinity error.");
   		return -1;
   	}
   	return 0;
}

unsigned long  cpu_get_affinity(void){
	cpu_set_t mask;
	unsigned long _mask =0;
	int cpu;
	if (sched_getaffinity(0, sizeof(mask), &mask) < 0) {
		fprintf(stderr,"sched_getaffinity");
		return 0;
	}
	
	for ( cpu = MAXnrCPUs -1 ; cpu >=0 ; cpu-- )
		_mask = _mask*2 + CPU_ISSET(cpu, &mask) ;
	PDEBUG("cpu_get_affiniti:my affinity mask is: %lx\n", _mask);
	return _mask;
}


